
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.ui.Component');
goog.require('goog.ui.Dialog')
goog.require('goog.ui.Ratings');
goog.require('goog.ui.ServerChart');
goog.require('goog.ui.SplitPane');
goog.require('goog.ui.SplitPane.Orientation');
goog.require('goog.ui.Zippy');
goog.require('goog.dom.ViewportSizeMonitor');



goog.provide('booksmap.Controller');
goog.provide('booksmap.SplitPane');
goog.provide('booksmap.MapViewer');
goog.provide('booksmap.SearchBox');

booksmap.controller = null;

booksmap.init = function(root_dom_id, map_canvas_dom_id, searchbox_dom_id, loader_img_dom_id){
	split_pane = new booksmap.SplitPane(root_dom_id);
	map_viewer = new booksmap.MapViewer(map_canvas_dom_id);
	searchbox  = new booksmap.SearchBox(searchbox_dom_id, map_viewer);

	booksmap.controller = new booksmap.Controller(split_pane, map_viewer, searchbox, loader_img_dom_id);
}


//
// booksmap.Controller
//

// constructor
booksmap.Controller = function(split_pane, map_viewer, searchbox, loader_img_dom_id){
	// init menber variables
	this.m_split_pane = split_pane;
	this.m_map_viewer = map_viewer;
	this.m_searchbox = searchbox;
	this.m_loader_img_dom = document.getElementById(loader_img_dom_id);

	var listener = this;

	// add event listeneres
	{
		var on_map_click = function(overlay, latlng, overlaylatlng) {
			var pt = map_viewer.fromLatLngToPoint(latlng);
			var url = "event_click?x=" + pt.x + "&y=" + pt.y + "&layer=" + map_viewer.getZoom();

			var request = GXmlHttp.create();
			request.open("GET", url, true);
			request.onreadystatechange = function() {
				if (request.readyState == 4){
					eval(request.responseText);
					if(node == null){
					}
					else if(node.is_browse_node == 1){
						listener.onSearch("browse_node_id", node.id, 1, node.label);
					}
					else{
						listener.onSearch("author", node.id, 1, node.label);
					}
				}
			}
			request.send(null);
		}
		map_viewer.addListener("click", on_map_click);

		var vsm = new goog.dom.ViewportSizeMonitor();
		var onresize = function(e){
			var size = new goog.math.Size(
				vsm.getSize().width  -  split_pane.getDom().offsetLeft - 10,
				vsm.getSize().height -  split_pane.getDom().offsetTop  - 10
			);
			split_pane.setSize(size);
			map_viewer.checkResize();
		}
		goog.events.listen(vsm, goog.events.EventType.RESIZE, onresize);

		onresize(null);
	}

	// create about dialog
	{
		this.m_about_dialog = new goog.ui.Dialog(null, true);
		this.m_about_dialog.setContent(
			'Books Map test version.<br\>' +
				'Powered by google.'
		);
		this.m_about_dialog.setTitle('About');
		this.m_about_dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
	}
}


booksmap.Controller.prototype.onAbout = function(){
	this.m_about_dialog.setVisible(true);
}

booksmap.Controller.prototype.onSearchByKeyword = function(keyword){
	this.onSearch("keyword", keyword, 1, keyword);
}

booksmap.Controller.prototype.onSearch = function(type, keyword, page_number, label){
	var request = GXmlHttp.create();
	var url = "aws_search_books?" + type + "=" + encodeURI(keyword) + "&page=" + page_number;

	this.m_loader_img_dom.style.visibility = "visible";

	request.open("GET", url, true);
	var listener = this;
	request.onreadystatechange = function() {
		if (request.readyState == 4){
			eval("var result=" + request.responseText);
			listener.m_searchbox.refresh(type, keyword, page_number, label, result);
			listener.m_loader_img_dom.style.visibility = "hidden";
		}
		else{
		}
	}
	request.send(null);
}


// booksmap.SplitPane
booksmap.SplitPane = function(dom_id){
    var lhs = new goog.ui.Component();
    var rhs = new goog.ui.Component();

	this.m_dom = document.getElementById(dom_id);
    this.m_splitpane =
		new goog.ui.SplitPane(lhs, rhs, goog.ui.SplitPane.Orientation.HORIZONTAL);
    this.m_splitpane.setInitialSize(384);
    this.m_splitpane.setHandleSize(4);
    this.m_splitpane.decorate(this.m_dom);
    this.m_splitpane.setContinuousResize(false);
}

booksmap.SplitPane.prototype.getDom = function(){
	return this.m_dom;
}

booksmap.SplitPane.prototype.setSize = function(size){
	return this.m_splitpane.setSize(size);
}


//
// booksmap.MapViewer
//
booksmap.TILE_OPACITY   = 1.0;
booksmap.TILE_IS_PNG    = false;
booksmap.TILE_SIZE      = 256;
booksmap.MIN_RESOLUTION = 0;
booksmap.MAX_RESOLUTION = 7;


// constructor
booksmap.MapViewer = function(dom_id){
	if (!GBrowserIsCompatible()) {
		return false;
	}

	this.m_projection = this.createCustomProjection();

	var mapCustom = new GMapType(
		[this.createCustomTileLayer()],
		this.m_projection,
		"");
	this.m_map_canvas_id = dom_id;
	this.m_map = new GMap2(document.getElementById(this.m_map_canvas_id), {mapTypes:[mapCustom]});
	this.m_map.setCenter(new GLatLng(0, 0), 2);
	this.m_map.enableDoubleClickZoom();
	this.m_map.enableContinuousZoom();
	this.m_map.enableScrollWheelZoom();
	// this.m_map.enableGoogleBar();

	// add controls
	this.m_map.addControl(new GLargeMapControl());

	// create marker icon
	{
		this.m_arrow_icon                   = new GIcon();
		this.m_arrow_icon.image             = "http://www.google.com/mapfiles/gadget/arrowSmall80.png";
		this.m_arrow_icon.shadow            = "http://www.google.com/mapfiles/gadget/arrowshadowSmall80.png";
		this.m_arrow_icon.iconSize          = new GSize(31, 27);
		this.m_arrow_icon.shadowSize        = new GSize(31, 27);
		this.m_arrow_icon.iconAnchor        = new GPoint(8, 27);
		this.m_arrow_icon.infoWindowAnchor  = new GPoint(5, 1);

		this.m_letter_icon                  = new GIcon(G_DEFAULT_ICON);
		this.m_letter_icon.shadow           = "http://www.google.com/mapfiles/shadow50.png";
		this.m_letter_icon.iconSize         = new GSize(20, 34);
		this.m_letter_icon.shadowSize       = new GSize(37, 34);
		this.m_letter_icon.iconAnchor       = new GPoint(9, 34);
		this.m_letter_icon.infoWindowAnchor = new GPoint(9, 2);
	}

	return true;
}


booksmap.MapViewer.prototype.checkResize = function(){
	this.m_map.checkResize();
}

booksmap.MapViewer.prototype.getZoom = function(){
	return this.m_map.getZoom();
}

booksmap.MapViewer.prototype.getLayerSize = function(layer){
        var size = booksmap.TILE_SIZE;
        for(var i = 0; i < layer; i++){
                size *= 2;
        }
        return size;
}

booksmap.MapViewer.prototype.addListener = function(event, handler){
	GEvent.addListener(this.m_map, event, handler);
}

booksmap.MapViewer.prototype.fromLatLngToPoint = function(latlng){
	var pt = this.m_projection.fromLatLngToPixel(latlng, this.getZoom());
	var size = this.getLayerSize(this.getZoom());
	pt.x = pt.x / size;
	pt.y = pt.y / size;
	return pt;
}

booksmap.MapViewer.prototype.fromPointToLatLng = function(pt){
	var size = this.getLayerSize(this.getZoom());
	pt.x = pt.x * size;
	pt.y = pt.y * size;
	var latlng = this.m_projection.fromPixelToLatLng(pt, this.getZoom());
	return latlng;
}


booksmap.MapViewer.prototype.createCustomTileLayer = function () {
	var dataLayer = new GTileLayer(
		new GCopyrightCollection(""),
		booksmap.MIN_RESOLUTION,
		booksmap.MAX_RESOLUTION
	);
	dataLayer.getOpacity = function(){ return booksmap.TILE_OPACITY; };
	dataLayer.isPng = function(){ return booksmap.TILE_IS_PNG; };
	dataLayer.getTileUrl = function(tile, zoom) {
		return "img_download/?name=img_" + ("00"+zoom).substr(-2) + "_" +
			("0000"+tile.x).substr(-4) +
			("0000"+tile.y).substr(-4) + ".png";
	};
	return dataLayer;
}


booksmap.MapViewer.prototype.createCustomProjection = function() {
	var proj = G_NORMAL_MAP.getProjection();
	proj.tileCheckRange = function (tile, zoom, tilesize) {
		var mapsize = Math.pow(2,zoom);
		if (tile.y < 0 || tile.y >= mapsize) {
			return false;
		}
		if (tile.x < 0 || tile.x >= mapsize) {
			return false;
		}
		return true;
	}
	return proj;
}


booksmap.MapViewer.prototype.addMarker = function(x, y, type) {
	var pt = new GPoint(x, y);
	var latlng = this.fromPointToLatLng(pt);
	var marker_options;
	var marker;

	if(type == "arrow"){
		marker_options = {icon:this.m_arrow_icon};
	}
	else{
		var letter_icon = new GIcon(this.m_letter_icon);
		letter_icon.image = "http://www.google.com/mapfiles/marker" + type + ".png";
		marker_options = { icon:letter_icon };
	}

	marker = new GMarker(latlng, marker_options);
	this.m_map.addOverlay(marker);

	return marker;
}


booksmap.MapViewer.prototype.clearMarkers = function(){
	this.m_map.clearOverlays();
}


//
// SearchBox
//
booksmap.SearchBox = function(dom_id, map_viewer){
	this.m_dom_id = dom_id;
	this.m_dom = document.getElementById(dom_id);
	this.m_map_viewer = map_viewer
	this.m_zippy = null;
}


booksmap.SearchBox.prototype.refresh = function(type, keyword, page_number, label, aws_result){
	var html = new Array();

	this.m_map_viewer.clearMarkers();

	// title
	var type_str = {
		"author": "著者",
		"browse_node_id": "分類",
		"keyword": "検索"
	};
	html.push("<h3>");
	if(aws_result.ParentX != null){ // marker
		var marker = this.m_map_viewer.addMarker(aws_result.ParentX, aws_result.ParentY, "arrow");
		html.push("<img src='", marker.getIcon().image, "'/>");
	}
	html.push(type_str[type], ":&nbsp;", label, "</h3>");

	// items
	var marker_hash = {};
	var marker_letter = "A"
	var items = aws_result.Items;
	for(var i = 0; i < items.length; i++){
		var detail_page_url  = items[i].DetailPageURL;
		var title            = items[i].Title;
		var publication_date = items[i].PublicationDate;
		var publisher        = items[i].Publisher;
		var authors          = items[i].Author;
		var img_url          = items[i].ImgURL;
		var img_width        = items[i].ImgWidth;
		var img_height       = items[i].ImgHeight;

		html.push("<div class='search-result'>");
		if(img_url != null){
			html.push("<div class='result-img'>",
					  "<img src='", img_url, "' width=", img_width, " height=", img_height, ">",
					  "</div>");
		}
		if(items[i].NodeX != null){ // add marker
			var marker = marker_hash[authors[0]];
			if(marker == null){
				marker = this.m_map_viewer.addMarker(items[i].NodeX, items[i].NodeY, marker_letter);
				marker_letter = String.fromCharCode(marker_letter.charCodeAt(0) + 1);
				marker_hash[authors[0]] = marker;
			}
			html.push("<img class='result-marker' src='", marker.getIcon().image, "'/>");
		}
		html.push("<div class='result-desc'>",
				  "<div class='result-title'><a href='", detail_page_url, "' target='_blank'>", title, "</a></div>",
				  authors.join(","), "<br/>", publication_date, "&nbsp;&nbsp;", publisher,
				  "</div></div><br/>");
	}

	// paginator
	{
		var total_results = aws_result.TotalResults;
		var total_pages   = aws_result.TotalPages;

		html.push("<div class='paginator'>",
				  "検索結果: ", total_results, "件<br/>");
		if(total_pages > 1){
			if(page_number > 1){
				html.push("<a class='paginator-button' ",
						  "onclick=\"booksmap.controller.onSearch('", type,
						  "','", keyword, "',", page_number-1, ",'", label, "')\">前へ</a>&nbsp;&nbsp;");
			}
			for(var i = Math.max(page_number - 3, 1); i <= Math.min(page_number + 3, total_pages); i++){
				if(i == page_number){
					html.push(String(i), "&nbsp;");
				}
				else{
					html.push("<a class='paginator-button' ",
							  "onclick=\"booksmap.controller.onSearch('", type,
							  "','", keyword, "',", i, ",'", label, "')\">", i, "</a>&nbsp;&nbsp;");
				}
			}
			if(page_number < total_pages){
				html.push("&nbsp;<a class='paginator-button' ",
						  "onclick=\"booksmap.controller.onSearch('", type,
						  "','", keyword, "',", page_number+1, ",'", label, "')\">次へ</a>&nbsp;&nbsp;");
			}
		}
		html.push("</div>");
	}

	// insert
	this.m_dom.innerHTML = html.join("");
	this.m_dom.scrollTop = 0;
}